/*
 * bootloader.c
 *
 *  Created on: 2012-6-8
 *      Author: Administrator
 */


#include "tangoc.h"

#define  RBUF   300
#define  WBUF   143

void input_bootloader(char *fname, char *cal)
{
	printf("Input fname: ");
	scanf("%s", fname);
	getchar();
	printf("Do you need calibration?(y/n)");
	scanf("%c", cal);
	getchar();
}

unsigned char hex2char(char c)
{
	return c < 'A' ? c - '0' : c - 'A' + 10;
}

int check_data(char *rbuf)
{
	int check = 0;
	if (!strncmp(rbuf, "$01", 3) || !strncmp(rbuf, "$06", 3)) return check;
	if (read(gdev, rbuf, 4) != 4)
	{
		check = 1;
		puts("Read check data Failed.");
	}
	if (rbuf[2] != 0)
	{
		check = 2;
		printf("Check data = %x %x %x %x\n", rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
		puts("Check status failed.");
	}
	printf("Check data = %x %x %x %x\n", rbuf[0], rbuf[1], rbuf[2], rbuf[3]);


//	int check = 0;
//	if (!strncmp(rbuf, "$01", 3) || !strncmp(rbuf, "$06", 3)) return check;
//	if (read(gdev, rbuf, 6) != 6)
//	{
//		check = 1;
//		puts("Read check data Failed.");
//	}
//	if (rbuf[2] != 0)
//	{
//		check = 2;
//		printf("Check data = %x %x %x %x\n", rbuf[0], rbuf[1], rbuf[2],
//				rbuf[3]);
//		puts("Check status failed.");
//	}
//	printf("Check data = %x %x %x %x\n", rbuf[0], rbuf[1], rbuf[2], rbuf[3]);


	return check;
}

//int check_version()
//{
//	int ver = bootloader_version()>>24;
//
//	return 0;
//}

int bootloader_mode(char *fname, char cal)
{
	int i, j, ret, len, check, version;
	FILE *fpix;
	char wbuf[WBUF];
	unsigned char N = 7, flag = 1, start = 1;

	fpix = fopen(fname, "r");
	if (fpix == NULL)
	{
		puts("Open file failed.");
		return -2;
	}
	ioctl(gdev, DISABLE_IRQ, 0);
	ioctl(gdev, BOOTLOADER_MODE, 0);//Bee
	while (1)
	{
		char rbuf[RBUF];
		fgets(rbuf, RBUF, fpix);
		if (feof(fpix)) break;
		if (!strncmp(rbuf, "!", 1))
		{
			printf("%s", rbuf);
			msleep(300);
			continue;
		}
		//else if (rbuf[0] != '$') continue;
		//else if (!strncmp(rbuf, "$00", 3))
	//	{
		//	flag = 0;
		//	ioctl(gdev, BOOTLOADER_MODE, 0);
	//	}
	/*	if ((!strncmp(rbuf, "$02", 3)||!strncmp(rbuf, "$03", 3) ||
			!strncmp(rbuf, "$04", 3) || !strncmp(rbuf, "$05", 3)) && flag) // auto write $00
		{
			flag = 0;
			ioctl(gdev, BOOTLOADER_MODE, 0);
//			for (i = 0; i < WBUF; i++) wbuf[i] = 0;
//			ret = write(gdev, wbuf, WBUF);
//			//msleep(100);
//			if (ret != WBUF)
//			{
//				puts("Write failed.");
//				break;
//			}

			puts("add $0 line");
		}*/

		for (i = 0; i < WBUF; i++)
		{
			wbuf[i] = (hex2char(rbuf[(i + 1) * 2 - 1]) << 4) | hex2char(rbuf[(i + 1) * 2]);
		}
		//printf("rbuf:%s\n", rbuf);

//		ret = write(gdev, wbuf, WBUF);
//		if (ret != WBUF)
//		{
//			puts("Write failed.");
//			break;
//		}

		printf("send 143 bytes.\n");
	/*	for(i=0; i<143; i++)
		{
			if(i%(N-1)==0 && i>0) printf("\n");
			printf("%3d ", wbuf[i]);
		}
		printf("\n");*/

		for(i=0; i<=143/(N-1); i++)
		{
			char tmp[8];
 // send Nbytes
			tmp[0] = i*(N-1);
			for(j=0; j<N-1; j++)
			{
				if(i<143/(N-1))	tmp[j+1] = wbuf[i*(N-1)+j];
				else
				{
					if(j<143%(N-1)) tmp[j+1] = wbuf[i*(N-1)+j];
					else tmp[j+1] = 0;
				}
			}

			ret = write(gdev, tmp, N);

			/*printf("N=%d i=%2d bytes:", N, i);
			for (j = 0; j < N; j++)
			{
				printf("%3d ", tmp[j]);
			}
			printf("\n");*/
			if (ret != N)
			{
				printf("write N bytes failed: ret=%d\n", ret);
			}
			msleep(2);
		}
		msleep(200);
		if(!strncmp(rbuf, "$01", 3) || !strncmp(rbuf, "$06", 3)) 
			msleep(100);
		check = check_data(rbuf);
		if (check > 0) break;
		if( start)
		{
			start = 0;
			msleep(20);
		}
		else
		{
			msleep(100);
		}
	}
	fclose(fpix);
	ioctl(gdev, RESET_TP, 0);
	msleep(100);
	ioctl(gdev, ENABLE_IRQ, 0);

	version = bootloader_version();
	if ( check != 0 )
	{
		puts("Download failed.");
		ret = -1;
	}
	else if( (version&0xff00) == 0xff)
	{
		printf("Download failed. version=%x\n", version);
		ret = -1;
	}
	else
	{
		puts("Download successfully.");
		ret = 0;
		if( cal=='y' ) ret = calibration();
	}

	return ret;
}


